#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Copyright © 启明星辰 版权所有
# @Time    : 2023/4/10 11:50
# @Author  : 胡浩浩
# @File    : api_doc_manage.py
# @IDE     : PyCharm
# @description : swagger接口文档管理
import asyncio
import json
import time

import requests
from pywebio.output import *
from pywebio.pin import put_input, pin, put_file_upload, put_textarea
from pywebio.session import eval_js

from apps.commons.comms import close_pop, replace_substring_in_list, IPADDRESS
from apps.commons.redis_tools import RedisClient
from apps.src.menus import show_menus
from config import APIPORT


def business_data_list():
    api_data_json = []
    print("huhaohao", api_data_json)
    result = requests.get(url=f"http://{IPADDRESS}:{APIPORT}/api_doc")
    print(result.json())
    list_data = result.json()
    list_data.reverse()
    for value in list_data:
        length = 0

        for item in value[4]:
            length += len(item["api_list"])
        exec_code = f"""
value[4] = put_row([
    put_button("接口列表", onclick=lambda : show_api_list_detail({value[4]},'{value[0]}'), small=True),
    put_button("删除", onclick=lambda: show_delete_info('{value[0]}', '{value[1]}'),color='danger', small=True)
],size="40%")
"""
        exec(exec_code)
        value.remove(value[5])

    return len(list_data), list_data


def show_delete_info(product_name, product_version):
    return popup(f'删除', [
        put_text("确认删除吗?"),
        put_row([
            None,
            put_button("确认", onclick=lambda: delete_api_doc(product_name, product_version), small=True),
            put_button("取消", onclick=lambda: close_popup(), color="dark", small=True)
        ], size="60%")

    ], size="normal", closable=False)


def delete_api_doc(product_name, product_version):
    print(product_name)
    print(product_version)
    # 查询数据库
    api_data_info = {
        "product_name": product_name,
        "product_version": product_version,
        "doc_name": "",
        "api_number": 0,
        "tags_json": "{}",
        "api_list": "{}"
    }

    result = requests.delete(url=f"http://{IPADDRESS}:{APIPORT}/api_doc", json=api_data_info)
    # print(result.json())
    toast(result.json()["message"])
    time.sleep(1)
    eval_js('window.location.reload();')


def show_api_list_detail(tags_json, product):
    toast("接口数据加载中，请稍后")
    data_list = []
    for tag in tags_json:
        api_list = []
        for item in tag["api_list"]:
            api_list.append(
                put_row([put_text(item.split("_")[0]), put_text(item.split("_")[1]), put_text(item.split("_")[2])],
                        size="6% 60%")
            )
        data_list.append(
            put_collapse(f'{tag["name"]}:{tag["description"]}', api_list, open=False)
        )

    popup(f'产品{product}接口列表', [
        put_scrollable(put_scope('scrollable'), height=700, keep_bottom=True),
        put_row([
            None,
            put_button("关闭", onclick=lambda: close_popup(), color="dark", small=True)
        ], size="89%")

    ], size="large", closable=False)
    put_table([[i] for i in data_list],
              header=[put_html('<div style="width:720px">请求方法---------接口------------------接口描述</div>')],
              scope="scrollable"),


def business_pages_data(total, data_list: list, current_page, search_keyword, table_header, page_size: int = 10):
    """
        第1页,start=0,end=10

        第2页strat=


    :return:
    """
    search_list = []
    print("search_keyword", search_keyword)
    if search_keyword != pin.api_search:
        search_keyword = pin.api_search
        if search_keyword:
            for f in data_list:
                if search_keyword in f[0] or search_keyword in f[1]:
                    search_list.append(f)
            data_list = search_list
            total = len(search_list)
            print(f"{time.strftime('%Y-%m-%d %H:%M:%S：')}", total)
            print(f"{time.strftime('%Y-%m-%d %H:%M:%S：')}", len(search_list))
            current_page = 1
        else:
            total, data_list = business_data_list()
            print(f"{time.strftime('%Y-%m-%d %H:%M:%S：')}", total)
            print(f"{time.strftime('%Y-%m-%d %H:%M:%S：')}", data_list)

        print("search_keyword", pin.api_search)

    print("current_page", current_page)
    if current_page < 1:
        current_page = 1
        toast("已经第一页了", color="#00BFFF")
        return
    if current_page > int(len(data_list) / page_size) + 1:
        current_page = int(len(data_list) / page_size) + 1
        toast("已经最后一页了", color="#00BFFF")
        return

    start_index = (current_page - 1) * page_size
    end_index = start_index + page_size
    if end_index >= len(data_list):
        end_index = len(data_list)
    with use_scope("data_list", clear=True):
        put_tabs(
            [
                {
                    "title": "swagger接口列表",
                    "content": [
                        put_button("上传", onclick=lambda: html_add_api_swagger(), small=True),
                        put_row(
                            [
                                put_text("搜素条件: "),
                                put_input(name="api_search", placeholder="请输入产品标识或者产品版本进行查询",
                                          value=search_keyword),
                                None,
                                put_button("搜索",
                                           onclick=lambda: business_pages_data(total, data_list, current_page,
                                                                               search_keyword, table_header),
                                           small=True),
                                put_button("重置",
                                           onclick=lambda: business_reset_data(1, total, data_list, table_header),
                                           small=True),
                            ], size="8% 50% 5% 6%"
                        ),
                        put_table(data_list[start_index:end_index],
                                  header=table_header),
                        put_row([
                            put_text(
                                f"      每页10条      当前第{current_page}/{int(total / 10) if total > 0 and total % 10 == 0 else int(total / 10) + 1}页     共{int(total / 10) if total > 0 and total % 10 == 0 else int(total / 10) + 1}页        总共{total}条"),
                            put_button("上一页", onclick=lambda: business_pages_data(total, data_list, current_page - 1,
                                                                                     search_keyword, table_header),
                                       small=True),
                            put_button("下一页", onclick=lambda: business_pages_data(total, data_list, current_page + 1,
                                                                                     search_keyword, table_header),
                                       small=True),
                        ], size="40% 6% 6%"
                        )

                    ]
                }
            ])


def business_reset_data(current_page, total, data_list, table_header):
    total, data_list = business_data_list()
    search_keyword = ""
    with use_scope("data_list", clear=True):
        put_tabs(
            [
                {
                    "title": "swagger接口列表",
                    "content": [
                        put_button("上传", onclick=lambda: html_add_api_swagger(), small=True),
                        put_row(
                            [
                                put_text("搜素条件: "),
                                put_input(name="api_search", placeholder="请输入产品标识或者产品版本进行查询"),
                                None,
                                put_button("搜索",
                                           onclick=lambda: business_pages_data(total, data_list, current_page,
                                                                               search_keyword, table_header),
                                           small=True),
                                put_button("重置",
                                           onclick=lambda: business_reset_data(1, total, data_list, table_header),
                                           small=True),
                            ], size="8% 50% 5% 6%"
                        ),
                        put_table(data_list[:10], header=table_header),
                        put_row([
                            put_text(
                                f"      每页10条      当前第{current_page}/{int(total / 10) if total > 0 and total % 10 == 0 else int(total / 10) + 1}页     共{int(total / 10) if total > 0 and total % 10 == 0 else int(total / 10) + 1}页        总共{total}条"),
                            put_button("上一页",
                                       onclick=lambda: business_pages_data(total, data_list, current_page - 1,
                                                                           search_keyword, table_header),
                                       small=True),
                            put_button("下一页",
                                       onclick=lambda: business_pages_data(total, data_list, current_page + 1,
                                                                           search_keyword, table_header),
                                       small=True),
                        ], size="40% 6% 6%"
                        )

                    ]
                }
            ], scope="data_list"
        )


def html_add_api_swagger():
    return popup('接口文档上传', [
        put_file_upload("swagger_json_file", accept='.json', placeholder="请选择需要上传的.json格式的接口文档"),
        put_row([
            None,
            put_button("提交", onclick=lambda: upload_api_swagger(), small=True),
            put_button('关闭', onclick=lambda: close_pop(), color="secondary", small=True)
        ], size="70% 15%"),

    ], size="normal", closable=False)


def upload_api_swagger():
    """
        上传swagger接口文档：

            将接口按组进行展示
            tags_json:{
            "token": [api_list]
            }


    :return:
    """
    swagger_json_file = pin.swagger_json_file
    if not swagger_json_file:
        toast("请选择接口文档以后,再进行提交", color="error")
        return
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S：')}", swagger_json_file["filename"])

    swagger_json = json.loads(swagger_json_file["content"].decode("utf-8"))
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S：')}", swagger_json["info"]["version"])
    if " " not in swagger_json["info"]["version"] or "_B" not in swagger_json["info"]["version"]:
        toast("版本号格式错误，停止上传,例如：TSOC-CSA v3.0.500.5.3.0_B20240716.1217", color="error")
        return
    product_version = str(swagger_json["info"]["version"]).replace(" ", ":").split("_")[0]
    print("处理接口分组逻辑")
    # 处理接口分组逻辑
    tags_list = []
    tags_json = swagger_json["tags"]
    for item in tags_json:
        tags_list.append(item["name"])
        item["api_list"] = []
    print(tags_json)
    print(tags_list)

    # 将接口数据存到对应的分组列表中
    path_json = swagger_json["paths"]
    tags_json.append(
        {
            "name": "default",
            "description": "",
            "api_list": [],
        }
    )
    tags_list.append("default")

    for path in path_json:
        print()
        for method in path_json[path]:
            # print(method)
            # print(path)
            # print(path_json[path][method].get("tags"))
            if path_json[path][method].get("tags"):
                for tg in path_json[path][method].get("tags"):
                    if tg in tags_list:
                        for tj in tags_json:
                            if tj["name"] == tg:
                                tj["api_list"].append(
                                    f"{method}_{path}_{path_json[path][method].get('summary') if path_json[path][method].get('summary') else ''}")
                    else:
                        # 这是一个新tag,需要处理一下新的tag
                        tags_list.append(tg)
                        tags_json.append(
                            {
                                "name": tg,
                                "description": "",
                                "api_list": [],
                            }
                        )
            else:
                # 处理一下不带tag的接口，将对应的接口存放到default组内
                print("我是没有tags的接口", path)
                # 只在第一次将default组加到tags_json中
                for tj in tags_json:
                    if tj["name"] == "default":
                        tj["api_list"].append(
                            f"{method}_{path}_{path_json[path][method].get('summary') if path_json[path][method].get('summary') else ''}")
    print()
    print(tags_json)

    path_number = len(list(swagger_json["paths"].keys()))
    # print(json.dumps(list(swagger_json["paths"].keys())))
    pattern = r"\{.*?\}"
    replacement = "{}"
    api_list = replace_substring_in_list(list(swagger_json["paths"].keys()), pattern, replacement)
    api_data_info = {
        "product_name": swagger_json["basePath"] if swagger_json.get("basePath") else swagger_json["info"]["version"].split(" ")[0],
        "product_version": product_version,
        "doc_name": swagger_json_file["filename"],
        "api_number": path_number,
        "tags_json": json.dumps(tags_json, ensure_ascii=False),
        "api_list": json.dumps(api_list, ensure_ascii=False)
    }
    result = requests.post(url=f"http://{IPADDRESS}:{APIPORT}/api_doc", json=api_data_info)
    # print(result.json())
    # 同步接口数据到Redis数据库中
    RedisClient().add(swagger_json["info"]["version"], swagger_json["basePath"] if swagger_json.get("basePath") else "", list(set(api_list)))
    toast(result.json()["message"])


def html_show_api():
    """
    接口文档
    """
    current_page = 1
    show_menus()
    total, data_list = business_data_list()
    search_keyword = ""
    table_header = [
        put_html('<h4 style="width:200px">产品标识</h4>'),
        put_html('<h4 style="width:250px">产品版本</h4>'),
        put_html('<h4 style="width:300px">接口文档名称</h4>'),
        put_html('<h4 style="width:200px">接口总数</h4>'),
        put_html('<h4 style="width:250px">操作</h4>'),
    ]
    put_tabs(
        [
            {
                "title": "swagger接口列表",
                "content": [
                    put_button("上传", onclick=lambda: html_add_api_swagger(), small=True),
                    put_row(
                        [
                            put_text("搜素条件: "),
                            put_input(name="api_search", placeholder="请输入产品标识或者产品版本进行查询"),
                            None,
                            put_button("搜索",
                                       onclick=lambda: business_pages_data(total, data_list, current_page,
                                                                           search_keyword, table_header), small=True),
                            put_button("重置", onclick=lambda: business_reset_data(1, total, data_list, table_header),
                                       small=True)
                        ], size="8% 50% 5% 6%"
                    ),
                    put_table(data_list[0:10],
                              header=table_header),
                    put_row([
                        put_text(
                            f"      每页10条      当前第{current_page}/{int(total / 10) if total > 0 and total % 10 == 0 else int(total / 10) + 1}页     共{int(total / 10) if total > 0 and total % 10 == 0 else int(total / 10) + 1}页        总共{total}条"),
                        put_button("上一页",
                                   onclick=lambda: business_pages_data(total, data_list, current_page - 1,
                                                                       search_keyword, table_header),
                                   small=True),
                        put_button("下一页",
                                   onclick=lambda: business_pages_data(total, data_list, current_page + 1,
                                                                       search_keyword, table_header),
                                   small=True),
                    ], size="40% 6% 6%"
                    )

                ]
            }
        ], scope="data_list"
    )
